package cn.ljy.authority.service.impl;

import cn.ljy.authority.dao.mapper.SysRoleMapper;
import cn.ljy.authority.dao.mapper.SysUserMapper;
import cn.ljy.authority.dao.mapper.SysUserRoleMapper;
import cn.ljy.authority.model.SysRole;
import cn.ljy.authority.model.SysUser;
import cn.ljy.authority.model.SysUserRole;
import cn.ljy.authority.service.SysUserRoleService;
import cn.ljy.common.exception.model.MyWebException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

/**
 * 账户和角色关系的业务类
 */
@Service
@Validated//表示开启sprint的校检框架，会自动扫描方法里的@Valid（@Valid注解一般写在接口即可）
@Slf4j
public class ISysUserRoleService implements SysUserRoleService {
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Override
    public void addUserRoles(Long[] userIds, Integer[] roleIds) {
        if(userIds==null||roleIds==null){
            throw new MyWebException("操作失败：非法参数");
        }
        if(userIds.length==0){
            throw new MyWebException("操作失败：请先选择账户");
        }
        if(roleIds.length==0){
            throw new MyWebException("操作失败：请选择要赋予的角色");
        }
//        if(userIds.length*roleIds.length>100){//批量赋予账户和角色的数量，避免数据库性能问题
//            throw new MyWebException("操作失败：一次赋予的账户和角色关系总数不能超过100个");
//        }
        //先遍历检查角色是否存在(一般是账户数量要多余角色数量，因此先检查角色效率会更高；否则应该先检查账户)
        Set<SysRole> roleSet=new HashSet<>();
        for(Integer roleId:roleIds){//遍历多个角色
            if(roleId==null){
                throw new MyWebException("操作失败：非法参数（角色id为空）");
            }
            SysRole role=sysRoleMapper.findById(roleId);
            if(role==null){
                throw new MyWebException("操作失败：角色"+role.getName()+"不存在");
            }
            roleSet.add(role);
        }
        //遍历检查账户是否存在
        Set<SysUser> userSet=new HashSet<>();
        for(Long userId:userIds) {
            if (userId == null) {
                throw new MyWebException("操作失败：非法参数（账户id为空）");
            }
            SysUser user = sysUserMapper.findByIdNoRelation(userId);
            if (user == null) {
                throw new MyWebException("操作失败：账户"+user.getUsername()+"不存在");
            }
            userSet.add(user);
        }
        //将要添加的关系存储到此集合中，用set是避免重复操作——但必须是已经对集合内对象的相等进行重写
        Set<SysUserRole> userRoleSet=new HashSet<>();
        for(SysUser user:userSet){
            for(SysRole role:roleSet){//遍历多个角色
                if(sysUserRoleMapper.countByUserIdAndRoleId(user.getId(),role.getId())==0){
                    //只有当不存在这个关系时才添加
                    userRoleSet.add(new SysUserRole(user,role,Calendar.getInstance().getTime()));
                }
            }
        }
        if(userRoleSet.size()>0){//只有集合大于0才执行保存。存在缺陷，如果前端在批量操作时重复传值，会导致一次出现多条记录的情况
            sysUserRoleMapper.saveAllIn(userRoleSet);
        }
    }

    @Override
    public void removeUserRoles(Long[] userIds, Integer[] roleIds) {
        if(userIds==null||roleIds==null){
            throw new MyWebException("操作失败：非法参数");
        }
        if(userIds.length==0){
            throw new MyWebException("操作失败：请先选择账户");
        }
        if(roleIds.length==0){
            throw new MyWebException("操作失败：请选择要移除的角色");
        }
        for(Integer roleId:roleIds){//遍历多个角色
            if(roleId==null){
                throw new MyWebException("操作失败：非法参数（角色id为空）");
            }
            SysRole role=sysRoleMapper.findById(roleId);
            if(role==null){
                throw new MyWebException("操作失败：角色"+role.getName()+"不存在");
            }
        }
        //遍历检查账户是否存在
        for(Long userId:userIds) {
            if (userId == null) {
                throw new MyWebException("操作失败：非法参数（账户id为空）");
            }
            SysUser user = sysUserMapper.findByIdNoRelation(userId);
            if (user == null) {
                throw new MyWebException("操作失败：账户"+user.getUsername()+"不存在");
            }
        }
        //将要添加的关系存储到此集合中，用set是避免重复操作——但必须是已经对集合内对象的相等进行重写
        Set<SysUserRole> userRoleSet=new HashSet<>();
        for(Long userId:userIds){//遍历多个账户
            for(Integer roleId:roleIds){//遍历多个角色
                if(sysUserRoleMapper.countByUserIdAndRoleId(userId,roleId)==1){
                    //只有当存在这个关系时才添加，也就是删除
                    userRoleSet.add(new SysUserRole(new SysUser(userId),new SysRole(roleId)));
                }
            }
        }
        if(userRoleSet.size()>0){//只有集合大于0才执行删除
            sysUserRoleMapper.deleteAllIn(userRoleSet);
        }
    }
}
